﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Controls;
using System.Reflection;

namespace Sinacor.Infra.UI.Controls.SmartClient.DataGrid
{
    public class DataGridCell : Microsoft.Windows.Controls.DataGridCell
    {
        #region Construtor
        public DataGridCell()
        {
            this.KeyDown += new KeyEventHandler(DataGridCell_KeyDown);
			AddHandler(DataGridCell.PreviewMouseDoubleClickEvent, new MouseButtonEventHandler(DataGridCell_PreviewMouseDoubleClick), true);
			AddHandler(DataGridCell.PreviewMouseLeftButtonDownEvent, new MouseButtonEventHandler(DataGridCell_PreviewMouseLeftButtonDown), false);
        }
        #endregion

        #region Row
		public DataGridRow Row
        {
            get { return (DataGridRow)this.GetType().GetProperty("RowOwner", System.Reflection.BindingFlags.GetProperty | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).GetValue(this, null); }
        }
	    #endregion

		#region DataGridCell_PreviewMouseLeftButtonDown
		void DataGridCell_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            e.Handled = true;
		}
		#endregion

		#region OnMouseLeftButtonUp
		protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
        {
            this.GetType().BaseType.InvokeMember("OnAnyMouseLeftButtonDown", BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.NonPublic, null, this, new object[] {e});
            base.OnMouseLeftButtonUp(e);
		}
		#endregion

		#region DataGridCell_KeyDown
		private void DataGridCell_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                if (!this.Row.IsEditing && this.IsReadOnly)
                {
                    this.OnConfirmSelection(this.Row.GetIndex(), this.Row.DataContext);
                }

                // TODO: Iniciar ou finalizar a edição da linha
                e.Handled = true;
            }
        }
        #endregion

        #region DataGridCell_MouseDoubleClick
		private delegate void DataGridCell_MouseDoubleClickHandler(object sender, MouseButtonEventArgs e);
		private void DataGridCell_PreviewMouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            if (!this.Row.IsEditing && this.IsReadOnly)
            {
                this.OnConfirmSelection(this.Row.GetIndex(), this.Row.DataContext);
            }
        }
        #endregion

        #region OnContentChanged
        protected override void OnContentChanged(object oldContent, object newContent)
        {
            base.OnContentChanged(oldContent, newContent);

            object toolTip = this.Column.GetType().InvokeMember("GenerateElement", System.Reflection.BindingFlags.InvokeMethod | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic, null, this.Column, new object[] { this, this.Row.Item });

            if (toolTip is ContentPresenter &&
                ((ContentPresenter)toolTip).ContentTemplate != null)
            {
                toolTip = ((ContentPresenter)toolTip).ContentTemplate.LoadContent();
            }

            // Gera tooltip a partir do conteúdo da célula
            this.ToolTip = toolTip;
        }
        #endregion

        #region ConfirmSelection
        public static readonly RoutedEvent ConfirmSelectionEvent = SinacorDataGrid.ConfirmSelectionEvent.AddOwner(typeof(DataGridCell));
        /// <summary>
        /// Evento disparado quando o usuário confima a seleção de um item
        /// </summary>
        public event ItemEventHandler ConfirmSelection
        {
            add { AddHandler(ConfirmSelectionEvent, value); }
            remove { RemoveHandler(ConfirmSelectionEvent, value); }
        }

        /// <summary>
        /// Dispara o evento <c>ConfirmSelection</c>
        /// </summary>
        /// <param name="element">Elemento que vai disparar o evento</param>
        /// <param name="index">Índice do item</param>
        /// <param name="item">Item</param>
        protected virtual void OnConfirmSelection(int index, object item)
        {
            ItemEventArgs e = new ItemEventArgs(ConfirmSelectionEvent, this, new ItemInfo(index, item));
            this.RaiseEvent(e);
        }
        #endregion

        #region ApplyStyle

        #region Constantes
        public const string DataGridCellBusiness01 = "DataGridCellBusiness01";
        public const string DataGridCellBusiness02 = "DataGridCellBusiness02";
        public const string DataGridCellBusiness03 = "DataGridCellBusiness03";
        public const string DataGridCellBusiness04 = "DataGridCellBusiness04";
        public const string DataGridCellBusiness05 = "DataGridCellBusiness05";
        public const string DataGridCellBusiness06 = "DataGridCellBusiness06";
        public const string DataGridCellBusiness07 = "DataGridCellBusiness07";
        #endregion

        #region ApplyingStyleEvent
        public static readonly RoutedEvent ApplyingStyleEvent = SinacorDataGrid.ApplyingStyleEvent.AddOwner(typeof(DataGridCell));

        /// <summary>
        /// Evento disparado depois do inicio da aplicação de um estilo 
        /// </summary>
        public event ApplyStyleHandler ApplyingStyle
        {
            add { AddHandler(ApplyingStyleEvent, value); }
            remove { RemoveHandler(ApplyingStyleEvent, value); }
        }

        /// <summary>
        /// Dispara o evento <c>ApplyingStyle</c>
        /// </summary>
        /// <param name="element">Elemento que vai disparar o evento</param>
        /// <param name="index">Índice do item</param>
        /// <param name="item">Item</param>
        /// <returns>Estilo a ser aplicado</returns>
        protected virtual string OnApplyingStyle(int index, object item)
        {
            ApplyStyleEventArgs e = new ApplyStyleEventArgs(ApplyingStyleEvent, this, new ItemInfo(index, item));
            this.RaiseEvent(e);
            return e.Style;
        }
        #endregion

        #region ApplyStyle
        /// <summary>
        /// Dispara evento ApplyingStyle e aplica estilo na célula conforme o retorno
        /// </summary>
        public void ApplyStyle()
        {
            string style = this.OnApplyingStyle(this.Row.GetIndex(), this.DataContext);
            if (string.IsNullOrEmpty(style))
                style = null;

            switch (style)
            {
                case DataGridCell.DataGridCellBusiness01:
                case DataGridCell.DataGridCellBusiness02:
                case DataGridCell.DataGridCellBusiness03:
                case DataGridCell.DataGridCellBusiness04:
                case DataGridCell.DataGridCellBusiness05:
                case DataGridCell.DataGridCellBusiness06:
                case DataGridCell.DataGridCellBusiness07:
                    // Aplicando estilo
                    this.SetResourceReference(StyleProperty, style);
                    break;

                case null:
                    // Limpando estilo
                    this.ClearValue(StyleProperty);
                    break;

                default:
                    // Estilo inválido
                    throw new InvalidOperationException(string.Format("Invalid cell style '{0}'", style));
            }
        }
        #endregion

        #endregion
    }
}